package com.dsl.benchmark;

import com.dsl.perfs.ExprEvalutorHelper;
import com.dsl.perfs.GroovyShellUtils;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

/**
 * 表达式基准测试(antlr对比groovy)
 *
 * @author evoup
 */
@SuppressWarnings("Duplicates")
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(value = 2, jvmArgs = {"-Xms4G", "-Xmx4G"})
// 默认Warmup和Measurement都是5
// @Warmup(iterations = 3)
// @Measurement(iterations = 8)
public class BenchmarkExpression {
    @Param({"10000000"})
    private int N;

    private String boolExpr = "1 && 2 || 3 || 4 && (5 || 6)";

    public static void main(String[] args) throws RunnerException {
        // https://stackoverflow.com/questions/24928922/jmh-what-does-the-score-value-mean
        if (args.length == 0) {
            System.out.println("请指定线程个数，在程序后空格加整型参数");
            System.exit(0);
        }
        Options opt = new OptionsBuilder()
                .include(BenchmarkExpression.class.getSimpleName())
                .forks(1).threads(Integer.valueOf(args[0])).build();
        new Runner(opt).run();
    }

    @Benchmark
    public void antlr(Blackhole bh) {
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Boolean> params = new TreeMap<>();
            params.put("1", random.nextBoolean());
            params.put("2", random.nextBoolean());
            params.put("3", random.nextBoolean());
            params.put("4", random.nextBoolean());
            params.put("5", random.nextBoolean());
            params.put("6", random.nextBoolean());
            bh.consume(ExprEvalutorHelper.exec(boolExpr, params));
            i++;
        }
    }

    @Benchmark
    public void groovy(Blackhole bh) {
        String nboolExpr = boolExpr;
        nboolExpr = nboolExpr.replace("1", "t1");
        nboolExpr = nboolExpr.replace("2", "t2");
        nboolExpr = nboolExpr.replace("3", "t3");
        nboolExpr = nboolExpr.replace("4", "t4");
        nboolExpr = nboolExpr.replace("5", "t5");
        nboolExpr = nboolExpr.replace("6", "t6");
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Object> params = new TreeMap<>();
            params.put("t1", random.nextBoolean());
            params.put("t2", random.nextBoolean());
            params.put("t3", random.nextBoolean());
            params.put("t4", random.nextBoolean());
            params.put("t5", random.nextBoolean());
            params.put("t6", random.nextBoolean());
            bh.consume(GroovyShellUtils.execExpr(nboolExpr, params, Boolean.class));
            i++;
        }
    }

}
